package ext.tianma.soap;

/**
 * @author Ken Shao
 * @version create
 * parser main class
 * use xsl file parse CAMP\EO XML file, and sent to sap
 */
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URL;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.SAXReader;

import wt.method.RemoteAccess;

import com.ptc.core.logging.Log;
import com.ptc.core.logging.LogFactory;

import ext.tianma.soap.conf.SOAPConfig;
import ext.tianma.soap.conf.SOAPConfigItem;

public class SOAPService implements RemoteAccess {
	// create a log
	private static Log log = LogFactory.getLog(SOAPService.class);

	public static final String Message_OK = "SUCCESS";
	public static final String Message_False = "FAIL";

	public SOAPService() {

	}

	public static CrmResponse sendProject(String soapData) throws Exception {
		SOAPConfig conf = new SOAPConfig();
		SOAPConfigItem item = conf.getConfigItem(SOAPConfig.SendProject);
		String actionName = item.getSoapAction();
		String endPoint = item.getEndpoint();
		String xsltFile = item.getXslt();
		// System.out.println(item);
		String res;
		res = SOAPService.callSoapService(endPoint, actionName, soapData, xsltFile);
		CrmResponse crmRes = parseCrmReponse(res);
		return crmRes;
	}

	public static CrmResponse parseCrmReponse(String response) {
		try {
			InputStream is = new ByteArrayInputStream(response.getBytes(), 0, response.getBytes().length);
			Document doc = parseXML(is);
			Element codeEle = (Element) doc.getRootElement();
			Element bodyEle = (Element) codeEle.elements().get(0);
			Element UpdateWithErrMsgOutEle = (Element) bodyEle.elements().get(0);
			Element UpdateWithErrMsgResultEle = (Element) UpdateWithErrMsgOutEle.elements().get(0);
			Element ErrorMsgEle = (Element) UpdateWithErrMsgOutEle.elements().get(1);
			CrmResponse crmRes = new CrmResponse();
			crmRes.setCode(UpdateWithErrMsgResultEle.getText());
			crmRes.setMsg(ErrorMsgEle.getText());
			return crmRes;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) {
		try {
			String testData = getProjectTestData();
			CrmResponse crmRes = sendProject(testData);
			if (crmRes == null) {
				System.out.println("parse error.");
			} else {
				System.out.println(crmRes);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * send soap request to endpoint. parse xmlcontent by xsltFile.
	 * 
	 * @param endPoint
	 * @param xmlContent
	 * @param xsltFile
	 * @param user
	 * @param password
	 * @return
	 */
	public static String callSoapService(String endPoint, String actionName, String xml) throws Exception {
		return callSoapService(endPoint, actionName, xml, null, null, null, false);
	}

	public static String callSoapService(String endPoint, String actionName, String xml, String xslFile) throws Exception {
		return callSoapService(endPoint, actionName, xml, xslFile, null, null, false);
	}

	/**
	 * send soap request to endpoint. parse xmlcontent by xsltFile.
	 * 
	 * @param endPoint
	 * @param xmlContent
	 * @param xsltFile
	 * @param user
	 * @param password
	 * @return
	 */
	public static String callSoapService(String endPoint, String actionName, String xml, String xsltFile, String user, String password, boolean writeLog)
			throws Exception {
		String xmlContent = xml;
		if (!xmlContent.startsWith("<")) {
			xmlContent = xmlContent.substring(xmlContent.indexOf("<"));
		}
		String serverHost = endPoint.substring(endPoint.indexOf("://") + "://".length());
		serverHost = serverHost.substring(0, serverHost.indexOf(":"));
		String serverPort = endPoint.substring(endPoint.indexOf(serverHost) + serverHost.length());
		serverPort = serverPort.substring(1, serverPort.indexOf("/"));
		javax.xml.transform.Source xmlSource = new javax.xml.transform.stream.StreamSource(new StringReader(xmlContent));
		javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(xsltFile);
		javax.xml.transform.TransformerFactory transFact = javax.xml.transform.TransformerFactory.newInstance();
		try {
			DocumentResult result = new DocumentResult();

			javax.xml.transform.Transformer trans = transFact.newTransformer(xsltSource);
			trans.transform(xmlSource, result);
			String resultStr = result.getDocument().asXML();
			 System.out.println("post xml:"+resultStr);
			PostMethod postMethod = new PostMethod(endPoint);
			if (actionName != null) {
				postMethod.addRequestHeader("SOAPAction", actionName);
			}
			byte[] b;
			b = resultStr.getBytes("utf-8");
			InputStream is = new ByteArrayInputStream(b, 0, b.length);
			RequestEntity re = new InputStreamRequestEntity(is, b.length, "text/xml;charset=UTF-8");
			postMethod.setRequestEntity(re);
			HttpClient httpClient = new HttpClient();
			// httpClient.getParams().setAuthenticationPreemptive(true);
			// httpClient.getState().setCredentials(new AuthScope(serverHost,
			// Integer.valueOf(serverPort), AuthScope.ANY_HOST),
			// null);
			org.apache.commons.httpclient.params.HttpClientParams p = new HttpClientParams();
			int statusCode = httpClient.executeMethod(postMethod);
			String soapResponseData = postMethod.getResponseBodyAsString();
			if (statusCode != 200) {
				throw (new Exception("Can not get response:" + endPoint + ", statusCode:" + statusCode + " response:" + soapResponseData));
			}
			postMethod.releaseConnection();
			// System.out.println(soapResponseData);
			return soapResponseData;
		} catch (Exception e) {
			e.printStackTrace();
			log.error(ExceptionUtils.getStackTrace(e));
			throw (e);
		}
	}

	public static Document parseXML(InputStream in) {
		try {
			SAXReader saxReader = new SAXReader();
			saxReader.setEntityResolver(new IgnoreDTDEntityResolver());
			Document doc = saxReader.read(in);
			return doc;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	
	public static String getProjectXmlData(String guid, String status, String phase,String estime, String cstime, String mptime, String problems, String issue) {
		String soapData = "<project>";
		soapData += "<UpadateJSON><![CDATA[{\"opportunity\": ["
				+ "{\"tm_plmprojectstatus\": {\"Value\": "
				+ status
				+ ","
				+ "                \"Type\": \"OptionSetValue\","
				+ "                \"LogicalName\": null,"
				+ "                \"Name\": null"
				+ "            },"
				+ "\"tm_opportunitystatus\": {\"Value\": "
				+ phase
				+ ","
				+ "                \"Type\": \"OptionSetValue\","
				+ "                \"LogicalName\": null,"
				+ "                \"Name\": null"
				+ "            },"
				+ "            \"tm_mptime\": {"
				+ "                \"Value\": \""
				+ mptime
				+ "\","
				+ "                \"Type\": \"DateTime\","
				+ "                \"LogicalName\": null,"
				+ "                \"Name\": null"
				+ "            },"
				+ "            \"tm_mainproblemsandimpacts\": {"
				+ "                \"Value\": \""
				+ problems
				+ "\","
				+ "                \"Type\": \"String\","
				+ "                \"LogicalName\": null,"
				+ "                \"Name\": null"
				+ "            },"
				+ "            \"tm_cstime\": {"
				+ "                \"Value\": \""
				+ cstime
				+ "\","
				+ "                \"Type\": \"DateTime\","
				+ "                \"LogicalName\": null,"
				+ "                \"Name\": null"
				+ "            },"
				+ "            \"tm_estime\": {"
				+ "                \"Value\": \""
				+ estime
				+ "\","
				+ "                \"Type\": \"DateTime\","
				+ "                \"LogicalName\": null,"
				+ "                \"Name\": null"
				+ "            },"
				+ "            \"tm_issuecountermeasure\": {"
				+ "                \"Value\": \""
				+ issue
				+ "\","
				+ "                \"Type\": \"String\","
				+ "                \"LogicalName\": null,"
				+ "                \"Name\": null"
				+ "            },"
				+ "            \"opportunityid\": {"
				+ "                \"Value\": \""
				+ guid
				+ "\","
				+ "                \"Type\": \"Guid\","
				+ "                \"LogicalName\": null,"
				+ "                \"Name\": null" + "            }" + "        }" + "    ]" + "}]]></UpadateJSON>";
		soapData += "<UserName>?</UserName>";
		soapData += "<PassWord>?</PassWord>";
		soapData += "<Location>?</Location>";
		soapData += "</project>";
		return soapData;
	}

	public static String getProjectTestData() {
		String soapData = "<project>";
		soapData += "<UpadateJSON><![CDATA[{" + "    \"opportunity\": [" + "        {" + "            \"tm_plmprojectstatus\": {"
				+ "                \"Value\": 930810000," + "                \"Type\": \"OptionSetValue\"," + "                \"LogicalName\": null,"
				+ "                \"Name\": null" + "            }," + "            \"tm_mptime\": {" + "                \"Value\": \"2016-03-01\","
				+ "                \"Type\": \"DateTime\"," + "                \"LogicalName\": null," + "                \"Name\": null" + "            },"
				+ "            \"tm_mainproblemsandimpacts\": {" + "                \"Value\": \"main prob<>&lem444\","
				+ "                \"Type\": \"String\"," + "                \"LogicalName\": null," + "                \"Name\": null" + "            },"
				+ "            \"tm_cstime\": {" + "                \"Value\": \"2016-03-02\"," + "                \"Type\": \"DateTime\","
				+ "                \"LogicalName\": null," + "                \"Name\": null" + "            }," + "            \"tm_estime\": {"
				+ "                \"Value\": \"2016-03-03\"," + "                \"Type\": \"DateTime\"," + "                \"LogicalName\": null,"
				+ "                \"Name\": null" + "            }," + "            \"tm_issuecountermeasure\": {"
				+ "                \"Value\": \"issue4444\"," + "                \"Type\": \"String\"," + "                \"LogicalName\": null,"
				+ "                \"Name\": null" + "            }," + "            \"opportunityid\": {"
				+ "                \"Value\": \"b75fe676-16b1-e411-be0c-005056be43e6\"," + "                \"Type\": \"Guid\","
				+ "                \"LogicalName\": null," + "                \"Name\": null" + "            }" + "        }" + "    ]" + "}]]></UpadateJSON>";
		soapData += "<UserName>?</UserName>";
		soapData += "<PassWord>?</PassWord>";
		soapData += "<Location>?</Location>";
		soapData += "</project>";
		return soapData;
	}

}
